/**
 * 作者:hanbo
 * 日期:2018/9/410:16
 * 描述:WebGL工具类
 */
export class WebGL {
    /**
     * 由canvas对象获取webGL上下文对象
     * @param {Element} canvas
     * @returns {*}
     */
    static getWebGLContext(canvas) {
        let names = ['webgl', 'experimental-webgl'];
        let context = null;
        for (let name of names) {
            try {
                context = canvas.getContext(name, {antialias: true});
                // {antialias:false}开启抗锯齿设置，Firefox中没有默认开启
            } catch (e) {
            }
            if (context) {
                break
            }
        }
        if (context) {
            context.viewportWidth = canvas.width;
            context.viewportHeight = canvas.height;
        } else {
            console.error('获取webgl对象失败');
            return;
        }
        return context;
    }

    /**
     * 编译着色器
     * @param gl
     * @param type
     * @param shaderSource
     * @returns {*}
     */
    static loadShader(gl, type, shaderSource) {
        let shader = gl.createShader(type);
        gl.shaderSource(shader, shaderSource);
        gl.compileShader(shader);

        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            console.error(`编译着色器失败${type}`);
            //编译失败删除着色器
            gl.deleteShader(shader);
            return null;
        }
        return shader;
    }

    static createProgram(gl, vshader, fshader) {
        // 创造着色器对象
        let vertexShader = WebGL.loadShader(gl, gl.VERTEX_SHADER, vshader);
        let fragmentShader = WebGL.loadShader(gl, gl.FRAGMENT_SHADER, fshader);
        if (!vertexShader || !fragmentShader) {
            return null;
        }

        // 创造 program 对象
        let program = gl.createProgram();
        if (!program) {
            return null;
        }

        // 绑定着色器与program
        gl.attachShader(program, vertexShader);
        gl.attachShader(program, fragmentShader);

        //连接program
        gl.linkProgram(program);

        // gl.deleteProgram(program)//删除着色器程序，释放内存

        // 检查连接结果
        let linked = gl.getProgramParameter(program, gl.LINK_STATUS);
        if (!linked) {
            let error = gl.getProgramInfoLog(program);
            console.log('连接 program失败: ' + error);
            gl.deleteProgram(program);
            gl.deleteShader(fragmentShader);
            gl.deleteShader(vertexShader);
            return null;
        }
        return {
            program: program,
            vertexShader: vertexShader,
            fragmentShader: fragmentShader
        };
    }

    /**
     * 初始化着色器
     * @param gl WebGL上下文对象
     * @param vshader 顶点着色器
     * @param fshader 片元着色器
     */
    static initShaders(gl, vshader, fshader) {
        let result = WebGL.createProgram(gl, vshader, fshader);
        if (!result) {
            console.log('创建program失败');
            return false;
        }
        gl.useProgram(result.program);
        return result;
    }
}